package com.code.origin.utils.encryption;

import cn.jiuxiaoer.third.common.utils.GsonUtils;
import cn.jiuxiaoer.third.eb.business.vo.EbBaseVo;
import cn.jiuxiaoer.third.eb.business.vo.EbRequestVo;
import cn.jiuxiaoer.third.eb.business.vo.EbResponseVo;
import cn.jiuxiaoer.third.eb.config.EbParamsConfig;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * 签名、加密工具类
 * @author my
 *
 */
public class SignUtil {

	/**
	 * MD5加密签名
	 * @param input 
	 * @return
	 */
	public static String getMD5(String input) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] messageDigest = md.digest(input.getBytes());
			BigInteger number = new BigInteger(1, messageDigest);
			String hashtext = number.toString(16);
			while (hashtext.length() < 32) {
				hashtext = "0" + hashtext;
			}
			return hashtext.toUpperCase();
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	/**
     * 校验签名是否正确
     * @return boolean
     */
    public static boolean checkSign(Map<String, Object> data, Map<String, Object> config) {
        Type type = new TypeToken<Map<String, Object>>() {}.getType();
        Gson gson = GsonUtils.getGsonDefault();
        data.put("body", gson.fromJson(data.get("body").toString(), type));

        String signFrom = getSign(data, config);
        String sign = data.get("sign").toString();
        if (signFrom.equals(sign)) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 校验签名是否正确
     * @return boolean
     */
    public static <T> boolean checkSign(EbResponseVo<T> vo, EbParamsConfig ebConfig, String bodyJson) {

        String signFrom = getSign(vo, ebConfig, bodyJson);
        String sign = vo.getSign();
        if (signFrom.equals(sign)) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 根据参数获取签名
     *
     * @param
     * @return String
     */
    public static String getSign(EbRequestVo vo, EbParamsConfig ebConfig) {
    	Object body = vo.getBody();
    	String cmd = vo.getCmd();
    	String ticket = vo.getTicket();
    	Object timestamp = vo.getTimestamp();
    	String source = vo.getSource();
    	String version = vo.getVersion();
    	String encrypt = vo.getEncrypt();
    	String secret = ebConfig.getSecret();
    	
    	return getSignByDataOrder(body, cmd, ticket, timestamp, source, version, encrypt, secret);
    }
    
    /**
     * 根据参数获取签名
     *
     * @param
     * @return String
     */
    public static <T> String getSign(EbResponseVo<T> vo, EbParamsConfig ebConfig, String bodyJson) {
    	Object body = vo.getBody();
    	String cmd = vo.getCmd();
    	String ticket = vo.getTicket();
    	Object timestamp = vo.getTimestamp();
    	String source = vo.getSource();
    	String version = vo.getVersion();
    	String encrypt = vo.getEncrypt();
    	String secret = ebConfig.getSecret();
    	
    	return getSignByDataOrder(body, cmd, ticket, timestamp, source, version, encrypt, secret);
    }
    
    /**
     * 根据参数获取签名
     *
     * @param
     * @return String
     */
    public static String getSign(EbBaseVo vo, Object body, EbParamsConfig ebConfig) {
    	String cmd = vo.getCmd();
    	String ticket = vo.getTicket();
    	Object timestamp = vo.getTimestamp();
    	String source = vo.getSource();
    	String version = vo.getVersion();
    	String encrypt = vo.getEncrypt();
    	String secret = ebConfig.getSecret();
    	
    	return getSignByDataOrder(body, cmd, ticket, timestamp, source, version, encrypt, secret);
    }
    
    /**
	 * 根据参数获取签名
	 * @return String
	 */
	public static String getSign(Map<String, Object> data) {
		Object body = data.get("body");
    	String cmd = data.get("cmd").toString();
    	String ticket = data.get("ticket").toString();
    	Object timestamp = data.get("timestamp");
    	String source = data.get("source").toString();
    	String version = data.get("version").toString();
    	String encrypt = "";
    	String secret = data.get("secret").toString();
    	
    	return getSignByDataOrder(body, cmd, ticket, timestamp, source, version, encrypt, secret);
	}
	
	/**
     * 根据参数获取签名
     *
     * @param
     * @return String
     */
    public static String getSign(Map<String, Object> data, Map<String, Object> config) {
    	Object body = data.get("body");
    	String cmd = data.get("cmd").toString();
    	String ticket = data.get("ticket").toString();
    	Object timestamp = data.get("timestamp");
    	String source = data.get("source").toString();
    	String version = data.get("version").toString();
    	String encrypt = "";
    	String secret = config.get("secret").toString();
    	
    	return getSignByDataOrder(body, cmd, ticket, timestamp, source, version, encrypt, secret);
    }
	
	private static String getSignByDataOrder(Object body, String cmd, String ticket, Object timestamp, String source, String version, String encrypt, String secret) {
    	TreeMap<String, Object> arr = new TreeMap<String, Object>();
    	arr.put("body", GsonUtils.getGsonDefault().toJson(body));
        arr.put("cmd", cmd);
        if (encrypt == null || "".equals(encrypt.trim())) {
        	encrypt = "";
        }
        arr.put("encrypt", encrypt);
        arr.put("secret", secret);
        arr.put("source", source);
        arr.put("ticket", ticket);
        arr.put("timestamp", timestamp);
        arr.put("version", version);
        
        StringBuilder strSignTmp = new StringBuilder("");
        Iterator<String> it = arr.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next().toString();
            strSignTmp.append(key + "=" + arr.get(key) + "&");
        }
        String strSign = strSignTmp.toString().substring(0, strSignTmp.length() - 1);
        
        String sign = getMD5(strSign.toString());
        
        return sign;
    }
}
